<?php
namespace zake\foundation\reactor\driver;

use zake\foundation\able\stream\DuplexDriverAble;
use zake\foundation\able\stream\ReadAble;
use zake\foundation\able\stream\ReadBufferAble;
use zake\foundation\able\stream\WriteAble;
use zake\foundation\able\stream\WriteBufferAble;
use zake\foundation\point\Segment;
use zake\foundation\stream\BufferReadStream;
use zake\foundation\stream\BufferWriteStream;


/**
 * Class Pipe
 * @package zake\foundation\channel
 *
 * 管道：单个管道通信方式为单向、FIFO模式；此处封装两条管道，用于模拟全双工的通信
 *
 * @author liu.bin 2020-03-31 10:25
 */
class PipeChannelAdapt implements DuplexDriverAble
{
    /**
     * 当前进程的pid
     * @var int
     */
    private $pid = 0;


    /**
     * 读
     * @var null|ReadBufferAble|ReadAble
     */
    private $readStream = null;

    /**
     * 写
     * @var null|WriteAble|WriteBufferAble
     */
    private $writeStream = null;


    /**
     * 构造器，在父进程中执行
     *
     * @param int $masterPid 父进程pid
     * @return DuplexDriverAble
     *
     * @author liu.bin 2020-03-30 15:27
     */
    public static function create($targetPid=null)
    {
        $self = new static($targetPid);
        return $self;
    }


    /**
     * 构造器
     *
     * Pipe constructor.
     *
     *
     */
    private function __construct($targetPid=null)
    {
        $this->pid  = posix_getpid();// 父 | 子
        $childPid   = is_null($targetPid) ? $this->pid : $targetPid;// 子
        $pipe0  = RUNTIME.'/channel/'.$childPid.'.0.pipe';
        $pipe1  = RUNTIME.'/channel/'.$childPid.'.1.pipe';
        if( !file_exists($pipe0) ){
            posix_mkfifo($pipe0, 0666);
        }
        if( !file_exists($pipe1) ){
            posix_mkfifo($pipe1, 0666);
        }
        if($childPid === $this->pid){
            // 0读，1写(子)
            $readResource     = fopen($pipe0, "r" );
            $writeResource    = fopen($pipe1, "w" );
        }else{
            // 0写，1读(父)
            $writeResource    = fopen($pipe0, "w" );
            $readResource     = fopen($pipe1, "r" );
        }
        $protocol = Segment::singleton();
        $this->readStream   = BufferReadStream::create($readResource);
        $this->readStream->setProtocol($protocol);
        $this->writeStream  = BufferWriteStream::create($writeResource);
        $this->writeStream->setProtocol($protocol);
    }


    /**
     * 获取 read stream
     *
     * @return null|ReadBufferAble|ReadAble
     * @author liu.bin 2020-03-30 15:19
     */
    public function getReadStream()
    {
        return $this->readStream;
    }


    /**
     * 获取 write stream
     *
     * @return null|WriteAble|WriteBufferAble
     * @author liu.bin 2020-03-31 15:58
     */
    public function getWriteStream()
    {
        return $this->writeStream;
    }

    /**
     * @param int $pid 当前进程id
     *
     * @author liu.bin 2020-04-06 00:36
     */
    public function init($pid)
    {
        // TODO: Implement init() method.
    }
}